using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace Space
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class InputComponent : Microsoft.Xna.Framework.GameComponent, IDataInput
    {
        MouseState mouseState;
        MouseState lastMouseState;
        GamePadState padState;
        GamePadState lastPadState;

        KeyboardState keys;
        KeyboardState lastKeys;

        object locker = null;

        public InputComponent(Game game)
            : base(game)
        {
            // TODO: Construct any child components here
            game.Services.AddService(typeof(IDataInput), this);
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            // TODO: Add your initialization code here

            base.Initialize();
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            lastMouseState = mouseState;
            lastKeys = keys;
            lastPadState = padState;

            keys = Keyboard.GetState();
            mouseState = Mouse.GetState();
            padState = GamePad.GetState(PlayerIndex.One, GamePadDeadZone.Circular);

            base.Update(gameTime);
        }

        public void Lock(object o)
        {
            locker = o;
        }

        public void Unlock(object o)
        {
            if (locker == o)
                locker = null;
        }

        public bool IsKeyClicked(Keys key, object locker = null)
        {
            if (this.locker != null && locker != this.locker) return false;
            return keys.IsKeyDown(key) && !lastKeys.IsKeyDown(key);
        }

        public bool IsButtonPressed(Buttons b, object locker = null)
        {
            if (this.locker != null && locker != this.locker) return false;
            return padState.IsButtonDown(b) && lastPadState.IsButtonUp(b);
        }

        public bool IsButtonDown(Buttons b, object locker = null)
        {
            if (this.locker != null && locker != this.locker) return false;
            return padState.IsButtonDown(b);
        }

        public Vector2 LeftThumbstick { get { return new Vector2(padState.ThumbSticks.Left.X, padState.ThumbSticks.Left.Y); } }
        public Vector2 RightThumbstick { get { return new Vector2(padState.ThumbSticks.Right.X, padState.ThumbSticks.Right.Y); } }
        public Vector2 MousePosition { get { return new Vector2(mouseState.X, mouseState.Y); } }
        public int ScrollWheelValue { get { return mouseState.ScrollWheelValue; } }
        public int ScrollWheelDelta { get { return mouseState.ScrollWheelValue - lastMouseState.ScrollWheelValue; } }

        public bool MouseRightReleased() { return mouseState.RightButton == ButtonState.Released && lastMouseState.RightButton == ButtonState.Pressed; }

        public bool IsKeyDown(Keys k)
        {
            return keys.IsKeyDown(k);
        }

        public float LeftTrigger { get { return padState.Triggers.Left; } }
    }
}
